﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Interactivity;
using Microsoft.Phone.Controls;
using Store.WP7.Framework.Animations;
using System.Windows.Controls.Primitives;
using System.Windows.Media.Imaging;
using Store.WP7.Framework.Extensions;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Windows.Navigation;

namespace Store.WP7.Framework.Interactions
{
    /// <summary>
    /// Animates an element so that it flies out and flies in!
    /// </summary>
    public class ContinuumDetailBehavior : Behavior<FrameworkElement>
    {
        #region TransitionBackground (DependencyProperty)

        /// <summary>
        /// A description of the property.
        /// </summary>
        public Brush TransitionBackground
        {
            get { return (Brush)GetValue(TransitionBackgroundProperty); }
            set { SetValue(TransitionBackgroundProperty, value); }
        }
        public static readonly DependencyProperty TransitionBackgroundProperty =
            DependencyProperty.Register("TransitionBackground", typeof(Brush), typeof(ContinuumDetailBehavior),
            new PropertyMetadata(null, new PropertyChangedCallback(OnTransitionBackgroundChanged)));

        private static void OnTransitionBackgroundChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((ContinuumDetailBehavior)d).OnTransitionBackgroundChanged();
        }

        protected virtual void OnTransitionBackgroundChanged()
        {
            if (_animation != null)
                _animation.TransitionBackground = TransitionBackground;
        }

        #endregion

        private PhoneApplicationFrame rootVisual
        {
            get { return Application.Current.RootVisual as PhoneApplicationFrame; }
        }

        private bool allowBack = false;

        private ContinuumAnimation _animation;

        /// <summary>
        /// Constructor
        /// </summary>
        public ContinuumDetailBehavior()
        {
            // Default transition background is from the phone
            TransitionBackground = Application.Current.Resources["PhoneBackgroundBrush"] as Brush;
        }

        protected override void OnAttached()
        {
            base.OnAttached();

            AssociatedObject.Loaded += Page_Loaded;
            AssociatedObject.Unloaded += Page_Unloaded;

            OnTransitionBackgroundChanged();

            _animation = new ContinuumAnimation();
            _animation.DetailItemFlyIn(this.AssociatedObject);
        }
        
        protected override void OnDetaching()
        {
            base.OnDetaching();

            AssociatedObject.Loaded -= Page_Loaded;
            AssociatedObject.Unloaded -= Page_Unloaded;
        }

        void Page_Unloaded(object sender, RoutedEventArgs e)
        {
            rootVisual.Navigating -= OnNavigating;
        }

        void Page_Loaded(object sender, RoutedEventArgs e)
        {
            rootVisual.Navigating += OnNavigating;

            allowBack = false;
        }

        /// <summary>
        /// If the user navigates to another page while the animation is playing, 
        /// the popup could still be visible on another page, so we need to hide it at this moment
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void OnNavigating(object sender, System.Windows.Navigation.NavigatingCancelEventArgs e)
        {
            if (!allowBack)
            {
                if (!e.Cancel && e.NavigationMode == NavigationMode.Back)
                {
                    _animation.SkipAnimation();

                    allowBack = true;

                    rootVisual.Navigating -= OnNavigating;

                    _animation.DetailItemFlyOut();
                    // Big disguting hack to hold on the navigation while 
                    // processing the animation through the composition thread
                    Dispatcher.BeginInvoke(() => Thread.Sleep((int)(ContinuumAnimation.FlyOutDuration * 1000)));
                }
            }
        }
    }
}
